home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / screen3 / part05 < prev    next >
Encoding:
Text File  |  1991-12-19  |  52.0 KB  |  2,399 lines

  1. Newsgroups: comp.sources.unix
  2. From: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  3. Subject: v25i045: Screen3 - multiple windows on an ASCII terminal, Part05/08
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: jnweiger@immd4.informatik.uni-erlangen.de (Juergen Weigert)
  8. Posting-Number: Volume 25, Issue 45
  9. Archive-Name: screen3/part05
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 5 (of 8)."
  18. # Contents:  fileio.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu Dec 19 17:36:05 1991
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'fileio.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'fileio.c'\"
  23. else
  24. echo shar: Extracting \"'fileio.c'\" \(49381 characters\)
  25. sed "s/^X//" >'fileio.c' <<'END_OF_FILE'
  26. X/* Copyright (c) 1991
  27. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  28. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  29. X * Copyright (c) 1987 Oliver Laumann
  30. X *
  31. X * This program is free software; you can redistribute it and/or modify
  32. X * it under the terms of the GNU General Public License as published by
  33. X * the Free Software Foundation; either version 1, or (at your option)
  34. X * any later version.
  35. X *
  36. X * This program is distributed in the hope that it will be useful,
  37. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. X * GNU General Public License for more details.
  40. X *
  41. X * You should have received a copy of the GNU General Public License
  42. X * along with this program (see the file COPYING); if not, write to the
  43. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44. X *
  45. X * Noteworthy contributors to screen's design and implementation:
  46. X *    Wayne Davison (davison@borland.com)
  47. X *    Patrick Wolfe (pat@kai.com, kailand!pat)
  48. X *    Bart Schaefer (schaefer@cse.ogi.edu)
  49. X *    Nathan Glasser (nathan@brokaw.lcs.mit.edu)
  50. X *    Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
  51. X *    Howard Chu (hyc@hanauma.jpl.nasa.gov)
  52. X *    Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
  53. X *    Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
  54. X *    Marc Boucher (marc@CAM.ORG)
  55. X *
  56. X ****************************************************************
  57. X */
  58. X
  59. X#ifndef lint
  60. X  static char rcs_id[] = "$Id: fileio.c,v 1.80 91/10/11 11:27:48 jnweiger Exp $ FAU";
  61. X#endif
  62. X
  63. X#if defined(pyr) || defined(MIPS) || defined(GOULD_NP1) || defined(B43)
  64. extern int errno;
  65. X#endif
  66. X#include <sys/types.h>
  67. X#include <sys/file.h>
  68. X#include <sys/stat.h>
  69. X#if defined(BSD) || defined(sequent) || defined(pyr)
  70. X# include <strings.h>
  71. X#else
  72. X# include <string.h>
  73. X#endif
  74. X#include <fcntl.h>
  75. X
  76. X#include "config.h"
  77. X#include "screen.h"
  78. X#include "extern.h"
  79. X
  80. X#ifdef _SEQUENT_
  81. X# define UTHOST        /* _SEQUENT_ has got ut_find_host() */
  82. X#endif
  83. X
  84. X#ifdef UTMPOK
  85. X# include <utmp.h>
  86. X#endif
  87. X
  88. X#ifndef GETUTENT
  89. X# ifdef GETTTYENT
  90. X#  include <ttyent.h>
  91. X# else
  92. struct ttyent
  93. X{
  94. X  char *ty_name;
  95. X};
  96. static char *tt, *ttnext;
  97. static char ttys[] = "/etc/ttys";
  98. X# endif
  99. X#endif
  100. X
  101. X#ifdef LOADAV
  102. X
  103. X#include <nlist.h>
  104. X
  105. static char KmemName[] = "/dev/kmem";
  106. X# if defined(_SEQUENT_) || defined(MIPS) || defined(SVR4)
  107. static char UnixName[] = "/unix";
  108. X# else
  109. X#  ifdef sequent
  110. static char UnixName[] = "/dynix";
  111. X#  else
  112. X#   ifdef hpux
  113. static char UnixName[] = "/hp-ux";
  114. X#   else
  115. X#    ifdef xelos
  116. static char UnixName[] = "/xelos";
  117. X#    else
  118. static char UnixName[] = "/vmunix";
  119. X#    endif
  120. X#   endif
  121. X#  endif
  122. X# endif
  123. X
  124. X# ifdef alliant
  125. static char AvenrunSym[] = "_Loadavg";
  126. X# else
  127. X#  if defined(hpux) || defined(_SEQUENT_) || defined(SVR4)
  128. static char AvenrunSym[] = "avenrun";
  129. X#  else
  130. static char AvenrunSym[] = "_avenrun";
  131. X#  endif
  132. X# endif
  133. static struct nlist nl[2];
  134. int avenrun;
  135. static kmemf;
  136. X# ifdef LOADAV_3LONGS
  137. long loadav[3];
  138. X# else
  139. X#  ifdef LOADAV_4LONGS
  140. long loadav[4];
  141. X#  else
  142. double loadav[3];
  143. X#  endif
  144. X# endif
  145. X
  146. X#endif /* LOADAV */
  147. X
  148. X#define BUFFERFILE "screen-exchange"
  149. X
  150. X
  151. X#if defined(UTMPOK) && defined(GETUTENT)
  152. extern struct utmp *getutline(), *pututline();
  153. X# if defined(_SEQUENT_)
  154. extern struct utmp *ut_add_user(), *ut_delete_user();
  155. extern char *ut_find_host();
  156. X# endif
  157. X#endif
  158. X#ifdef NETHACK
  159. extern nethackflag;
  160. X#endif
  161. X
  162. extern char *RcFileName, *home, *extra_incap, *extra_outcap;
  163. extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[];
  164. extern char *PowDetachString, *VisualBellString;
  165. extern int VBellWait, MsgWait, MsgMinWait;
  166. extern struct key ktab[];
  167. extern char Esc, MetaEsc;
  168. extern char *shellaka, SockPath[], *SockNamePtr, *LoginName;
  169. extern loginflag, TtyMode, auto_detach;
  170. extern iflag, mflag, rflag, dflag;
  171. extern flowctl, wrap;
  172. extern HS, termcapHS, use_hardstatus, visual_bell, default_monitor;
  173. extern default_histheight;
  174. extern default_startup;
  175. extern slowpaste;
  176. extern DeadlyMsg, HasWindow;
  177. extern ForeNum, screenwidth, screenheight;
  178. extern struct win *fore;
  179. extern char screenterm[];
  180. extern int join_with_cr;
  181. extern struct mode OldMode, NewMode;
  182. extern int HasWindow;
  183. extern char mark_key_tab[];
  184. extern int real_uid, eff_uid;
  185. extern int real_gid, eff_gid;
  186. X
  187. X#ifdef PASSWORD
  188. int CheckPassword;
  189. char Password[20];
  190. X#endif
  191. X
  192. X#ifdef COPY_PASTE
  193. extern char *copybuffer;
  194. extern copylen;
  195. X#endif
  196. X
  197. static char *CatExtra __P((char *, char *));
  198. static char **SaveArgs __P((int, char **));
  199. static int Parse __P((char *, char **));
  200. static int IsNum __P((char *, int));
  201. static int IsNumColon __P((char *, int, char *));
  202. static char *stripdev __P((char *));
  203. static slot_t TtyNameSlot __P((char *));
  204. X
  205. X#if !defined(GETTTYENT) && !defined(GETUTENT)
  206. static void setttyent __P((void));
  207. static struct ttyent *getttyent __P((void));
  208. X#endif
  209. X
  210. X/*
  211. X * XXX: system
  212. X */
  213. extern time_t time __P((time_t *));
  214. X#ifndef SVR4
  215. extern char *getpass __P((char *));
  216. X# ifdef LOADAV
  217. extern int nlist __P((char *, struct nlist *));
  218. X# endif
  219. X#endif
  220. X
  221. char *KeyNames[] = 
  222. X{
  223. X  "screen",
  224. X  "select0", "select1", "select2", "select3", "select4",
  225. X  "select5", "select6", "select7", "select8", "select9",
  226. X  "aka", "autoflow", "clear", "colon", "copy", "detach", "flow",
  227. X  "hardcopy", "help", "history", "info", "kill", "lastmsg", "license",
  228. X  "lockscreen", "log", "login", "monitor", "next", "other", "paste",
  229. X  "pow_detach", "prev", "quit", "readbuf", "redisplay", "removebuf",
  230. X  "reset", "set", "shell", "suspend", "termcap", "time", "vbell",
  231. X  "version", "width", "windows", "wrap", "writebuf", "xoff", "xon",
  232. X  0,
  233. X};
  234. X
  235. X
  236. X/* Must be in alpha order !!! */
  237. X
  238. char *RCNames[] =
  239. X{
  240. X  "activity", "all", "autodetach", "bell", "bind", "chdir", "crlf",
  241. X  "echo", "escape", "flow", "hardstatus", "login", "markkeys", "mode",
  242. X  "monitor", "msgminwait", "msgwait", "nethack", "password",
  243. X  "pow_detach_msg", "screen", "scrollback", "shell", "shellaka",
  244. X  "sleep", "slowpaste", "startup_message", "term", "termcap",
  245. X  "terminfo", "vbell", "vbell_msg", "vbellwait", "visualbell",
  246. X  "visualbell_msg", "wrap",
  247. X};
  248. X
  249. enum RCcases
  250. X{
  251. X  RC_ACTIVITY,
  252. X  RC_ALL,
  253. X  RC_AUTODETACH,
  254. X  RC_BELL,
  255. X  RC_BIND,
  256. X  RC_CHDIR,
  257. X  RC_CRLF,
  258. X  RC_ECHO,
  259. X  RC_ESCAPE,
  260. X  RC_FLOW,
  261. X  RC_HARDSTATUS,
  262. X  RC_LOGIN,
  263. X  RC_MARKKEYS,
  264. X  RC_MODE,
  265. X  RC_MONITOR,
  266. X  RC_MSGMINWAIT,
  267. X  RC_MSGWAIT,
  268. X  RC_NETHACK,
  269. X  RC_PASSWORD,
  270. X  RC_POW_DETACH_MSG,
  271. X  RC_SCREEN,
  272. X  RC_SCROLLBACK,
  273. X  RC_SHELL,
  274. X  RC_SHELLAKA,
  275. X  RC_SLEEP,
  276. X  RC_SLOWPASTE,
  277. X  RC_STARTUP_MESSAGE,
  278. X  RC_TERM,
  279. X  RC_TERMCAP,
  280. X  RC_TERMINFO,
  281. X  RC_VBELL,
  282. X  RC_VBELL_MSG,
  283. X  RC_VBELLWAIT,
  284. X  RC_VISUALBELL,
  285. X  RC_VISUALBELL_MSG,
  286. X  RC_WRAP,
  287. X  RC_RCEND,
  288. X};
  289. X
  290. X
  291. X#ifdef UTMPOK
  292. static utmp, utmpf;
  293. static char UtmpName[] = "/etc/utmp";
  294. X# ifdef MIPS
  295. X  static utmpfappend;
  296. X# endif
  297. X#endif
  298. X
  299. static FILE *fp = NULL;
  300. static char *rc_name;
  301. X
  302. char *SaveStr(str)
  303. register char *str;
  304. X{
  305. X  register char *cp;
  306. X
  307. X  if ((cp = malloc((unsigned) strlen(str) + 1)) == NULL)
  308. X    Msg_nomem;
  309. X  else
  310. X    strcpy(cp, str);
  311. X  return cp;
  312. X}
  313. X
  314. static char *CatExtra(str1, str2)
  315. register char *str1, *str2;
  316. X{
  317. X  register char *cp;
  318. X  register int len1, len2, add_colon;
  319. X
  320. X  len1 = strlen(str1);
  321. X  if (len1 == 0)
  322. X    return(str2);
  323. X  add_colon = (str1[len1 - 1] != ':');
  324. X  if (str2)
  325. X    {
  326. X      len2 = strlen(str2);
  327. X      if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL)
  328. X    Msg_nomem;
  329. X      bcopy(cp, cp + len1 + add_colon, len2 + 1);
  330. X    }
  331. X  else
  332. X    {
  333. X      if (len1 == 0)
  334. X    return 0;
  335. X      if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL)
  336. X    Msg_nomem;
  337. X    }
  338. X  bcopy(str1, cp, len1);
  339. X  if (add_colon)
  340. X    cp[len1] = ':';
  341. X
  342. X  return cp;
  343. X}
  344. X
  345. static char *findrcfile(rcfile)
  346. char *rcfile;
  347. X{
  348. X  static char buf[256];
  349. X  char *rc, *p;
  350. X
  351. X  if (rcfile)
  352. X    {
  353. X      rc = SaveStr(rcfile);
  354. X      debug1("findrcfile: you specified '%s'\n", rcfile);
  355. X    }
  356. X  else
  357. X    {
  358. X      debug("findrcfile: you specified nothing...\n");
  359. X      if ((p = getenv("ISCREENRC")) != NULL && *p != '\0')
  360. X    {
  361. X      debug1("  ... but $ISCREENRC has: '%s'\n", p);
  362. X      rc = SaveStr(p);
  363. X    }
  364. X      else if ((p = getenv("SCREENRC")) != NULL && *p != '\0')
  365. X    {
  366. X      debug1("  ... but $SCREENRC has: '%s'\n", p);
  367. X      rc = SaveStr(p);
  368. X    }
  369. X      else
  370. X    {
  371. X      debug("  ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n");
  372. X      if ((unsigned)strlen(home) > 244)
  373. X        Msg(0, "Rc: home too large");
  374. X      sprintf(buf, "%s/.iscreenrc", home);
  375. X          if (access(buf, R_OK))
  376. X        sprintf(buf, "%s/.screenrc", home);
  377. X      rc = SaveStr(buf);
  378. X    }
  379. X    }
  380. X  return rc;
  381. X}
  382. X
  383. X/*
  384. X * this will be called twice:
  385. X * 1) rcfilename = "/etc/screenrc"
  386. X * 2) rcfilename = RcFileName
  387. X */
  388. void
  389. StartRc(rcfilename)
  390. char *rcfilename;
  391. X{
  392. X  register int argc, len;
  393. X  register char *p, *cp;
  394. X  char buf[256];
  395. X  char *args[MAXARGS], *t;
  396. X
  397. X  rc_name = findrcfile(rcfilename);
  398. X
  399. X  if ((fp = secfopen(rc_name, "r")) == NULL)
  400. X    {
  401. X      if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  402. X    {
  403. X          /*
  404. X           * User explicitly gave us that name,
  405. X           * this is the only case, where we get angry, if we can't read
  406. X           * the file.
  407. X           */
  408. X      debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename);
  409. X          Msg(0, "Unable to open \"%s\".", rc_name);
  410. X      /* NOTREACHED */
  411. X    }
  412. X      debug1("StartRc: '%s' no good. ignored\n", rc_name);
  413. X      Free(rc_name);
  414. X      rc_name = "";
  415. X      return;
  416. X    }
  417. X  if ((t = getenv("TERM")) == NULL)
  418. X    Msg(0, "No TERM in environment.");
  419. X  debug1("startrc got termcp:%s\n", t);
  420. X  while (fgets(buf, sizeof buf, fp) != NULL)
  421. X    {
  422. X      if ((p = rindex(buf, '\n')) != NULL)
  423. X    *p = '\0';
  424. X      if ((argc = Parse(buf, args)) == 0)
  425. X    continue;
  426. X      if (strcmp(args[0], "echo") == 0)
  427. X    {
  428. X      if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3)
  429. X        {
  430. X          DeadlyMsg = 0;
  431. X          Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
  432. X        }
  433. X      else
  434. X        {
  435. X          printf((argc == 3) ? "%s" : "%s\r\n", args[argc - 1]);
  436. X        }
  437. X    }
  438. X      else if (strcmp(args[0], "sleep") == 0)
  439. X    {
  440. X      if (argc != 2)
  441. X        {
  442. X          DeadlyMsg = 0;
  443. X          Msg(0, "%s: sleep: one numeric argument expected.", rc_name);
  444. X        }
  445. X      else
  446. X        sleep(atoi(args[1]));
  447. X    }
  448. X#ifdef TERMINFO
  449. X      else if (strcmp(args[0], "terminfo") == 0)
  450. X#else
  451. X      else if (strcmp(args[0], "termcap") == 0)
  452. X#endif
  453. X    {
  454. X      if (argc < 3 || argc > 4)
  455. X        Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]);
  456. X      for (p = args[1]; p && *p; p = cp)
  457. X        {
  458. X          if ((cp = index(p, '|')) != 0)
  459. X        *cp++ = '\0';
  460. X          len = strlen(p);
  461. X          if (p[len - 1] == '*')
  462. X        {
  463. X          if (!(len - 1) || !strncmp(p, t, len - 1))
  464. X            break;
  465. X        }
  466. X          else if (!strcmp(p, t))
  467. X        break;
  468. X        }
  469. X      if (!(p && *p))
  470. X        continue;
  471. X      extra_incap = CatExtra(args[2], extra_incap);
  472. X      if (argc == 4)
  473. X        extra_outcap = CatExtra(args[3], extra_outcap);
  474. X    }
  475. X    }
  476. X  fclose(fp);
  477. X  Free(rc_name);
  478. X  rc_name = "";
  479. X}
  480. X
  481. char *ParseChar(p, cp)
  482. char *p, *cp;
  483. X{
  484. X  if (*p == '^')
  485. X    {
  486. X      if (*++p == '?')
  487. X        *cp = '\177';
  488. X      else if (*p >= '@')
  489. X        *cp = Ctrl(*p);
  490. X      else
  491. X        return 0;
  492. X      ++p;
  493. X    }
  494. X  else if (*p == '\\' && *++p <= '7' && *p >= '0')
  495. X    {
  496. X      *cp = 0;
  497. X      do
  498. X        *cp = *cp * 8 + *p - '0';
  499. X      while (*++p <= '7' && *p >= '0');
  500. X    }
  501. X  else
  502. X    *cp = *p++;
  503. X  return p;
  504. X}
  505. X
  506. X/*
  507. X * CompileKeys must be called before Markroutine is first used.
  508. X * to initialise the keys with defaults, call CompileKeys(NULL, mark_key_tab);
  509. X *
  510. X * s is an ascii string in a termcap-like syntax. It looks like
  511. X *   "j=u:k=d:l=r:h=l: =.:" and so on...
  512. X * this example rebinds the cursormovement to the keys u (up), d (down),
  513. X * l (left), r (right). placing a mark will now be done with ".".
  514. X */
  515. int CompileKeys(s, array)
  516. char *s, *array;
  517. X{
  518. X  int i;
  519. X  unsigned char key, value;
  520. X
  521. X  if (!s || !*s)
  522. X    {
  523. X      for (i = 0; i < 256; i++)
  524. X        array[i] = i;
  525. X      return 0;
  526. X    }
  527. X  while (*s)
  528. X    {
  529. X      s = ParseChar(s, (char *) &key);
  530. X      if (*s != '=')
  531. X    return -1;
  532. X      do 
  533. X    {
  534. X          s = ParseChar(++s, (char *) &value);
  535. X      array[value] = key;
  536. X    }
  537. X      while (*s == '=');
  538. X      if (!*s) 
  539. X    break;
  540. X      if (*s++ != ':')
  541. X    return -1;
  542. X    }
  543. X  return 0;
  544. X}
  545. X
  546. static char **SaveArgs(argc, argv)
  547. register int argc;
  548. register char **argv;
  549. X{
  550. X  register char **ap, **pp;
  551. X
  552. X  if ((pp = ap = (char **) malloc((unsigned) (argc + 1) * sizeof(char **))) == 0)
  553. X    Msg_nomem;
  554. X#ifdef notdef
  555. X  debug("saveargs:\n"); 
  556. X#endif
  557. X  while (argc--)
  558. X    {
  559. X      debug1(" '%s'", *argv);
  560. X      *pp++ = SaveStr(*argv++);
  561. X    }
  562. X  debug("\n");
  563. X  *pp = 0;
  564. X  return ap;
  565. X}
  566. X
  567. void
  568. AbortRc()
  569. X{
  570. X  debug("AbortRc();\n");
  571. X  if (fp == NULL)
  572. X    debug(" fp not open\n")
  573. X  else
  574. X    (void) fclose(fp);
  575. X}
  576. X
  577. void
  578. XFinishRc(rcfilename)
  579. char *rcfilename;
  580. X{
  581. X  /* in FinishRc screen is not yet open, thus Msg() is deadly here.
  582. X   */
  583. X  char buf[256];
  584. X
  585. X  rc_name = findrcfile(rcfilename);
  586. X
  587. X  if ((fp = secfopen(rc_name, "r")) == NULL)
  588. X    {
  589. X      if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  590. X    {
  591. X          /*
  592. X        * User explicitly gave us that name, 
  593. X       * this is the only case, where we get angry, if we can't read
  594. X       * the file.
  595. X       */
  596. X        debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename);
  597. X          Msg(0, "Unable to open \"%s\".", rc_name);
  598. X      /* NOTREACHED */
  599. X    }
  600. X      debug1("FinishRc: '%s' no good. ignored\n", rc_name);
  601. X      Free(rc_name);
  602. X      rc_name = "";
  603. X      return;
  604. X    }
  605. X
  606. X  debug("finishrc is going...\n");
  607. X  while (fgets(buf, sizeof buf, fp) != NULL)
  608. X    {
  609. X      RcLine(buf);
  610. X    }
  611. X  (void) fclose(fp);
  612. X  Free(rc_name);
  613. X  rc_name = "";
  614. X}
  615. X
  616. X/*
  617. X * this is a KEY_SET pressed
  618. X */
  619. void
  620. DoSet(argv)
  621. char **argv;
  622. X{
  623. X  char *p;
  624. X  static char buf[256];
  625. X
  626. X  p = buf;
  627. X  debug("DoSet\n");
  628. X  if (!argv || !*argv || !**argv)
  629. X    {
  630. X      debug("empty DoSet\n");
  631. X      sprintf(buf, "set ");
  632. X      RcLine(buf);
  633. X      return;
  634. X    }
  635. X  sprintf(p, "set"); p+=3;
  636. X  while(*argv && ((unsigned)strlen(buf) + (unsigned)strlen(*argv) < 255))
  637. X    {
  638. X      sprintf(p, " %s", *argv++);
  639. X      p += strlen(p);
  640. X    }
  641. X  RcLine(buf);
  642. X}
  643. X
  644. X/*
  645. X *    "$HOST blafoo"       -> "localhost blafoo"
  646. X *    "${HOST}blafoo"          -> "localhostblafoo"
  647. X *    "\$HOST blafoo"     -> "$HOST blafoo"
  648. X *    "\\$HOST blafoo"    -> "\localhost blafoo"
  649. X *    "'$HOST ${HOST}'"    -> "'$HOST ${HOST}'" 
  650. X *    "'\$HOST'"           -> "'\$HOST'"
  651. X *    "\'$HOST' $HOST"       -> "'localhost' $HOST"
  652. X */
  653. static char *expand_env_vars(ss)
  654. char *ss;
  655. X{
  656. X  static char ebuf[2048];
  657. X  register int esize = 2047, quofl = 0;
  658. X  register char *e = ebuf;
  659. X  register char *s = ss;
  660. X  register char *v;
  661. X
  662. X  while (*s && *s != '\n' && esize > 0)
  663. X    {
  664. X      if (*s == '\'')
  665. X    quofl ^= 1;
  666. X      if (*s == '$' && !quofl)
  667. X    {
  668. X      char *p, c;
  669. X
  670. X      p = ++s;
  671. X      if (*s == '{')
  672. X        {
  673. X          p = ++s;
  674. X          while (*p != '}')
  675. X            if (*p++ == '\0')
  676. X              return ss;
  677. X        }
  678. X      else
  679. X        {
  680. X          while (*p != ' ' && *p != '\0' && *p != '\n')
  681. X        p++;
  682. X        }
  683. X      c = *p;
  684. X      debug1("exp: c='%c'\n", c);
  685. X      *p = '\0';
  686. X      if (v = getenv(s)) 
  687. X        {
  688. X          debug2("exp: $'%s'='%s'\n", s, v);
  689. X          while (*v && esize-- > 0)
  690. X            *e++ = *v++;
  691. X        }
  692. X      else 
  693. X        debug1("exp: '%s' not env\n", s);
  694. X      if ((*p = c) == '}')
  695. X        p++;
  696. X      s = p;
  697. X    }
  698. X      else
  699. X    {
  700. X      if (s[0] == '\\' && !quofl)
  701. X        if (s[1] == '$' || (s[1] == '\\' && s[2] == '$') ||
  702. X            s[1] == '\'' || (s[1] == '\\' && s[2] == '\''))
  703. X          s++;
  704. X      *e++ = *s++;
  705. X      esize--;
  706. X    }
  707. X    }
  708. X  if (esize <= 0)
  709. X    Msg(0, "expand_env_vars: buffer overflow\n");
  710. X  *e = '\0';
  711. X  return ebuf;
  712. X}
  713. X
  714. void
  715. RcLine(ubuf)
  716. char *ubuf;
  717. X{
  718. X  char *args[MAXARGS];
  719. X  register char *buf, *p, **pp, **ap;
  720. X  register int argc, setflag;
  721. X  int q, qq;
  722. X  char key;
  723. X  int low, high, mid, x;
  724. X
  725. X  buf = expand_env_vars(ubuf); 
  726. X
  727. X  ap = args;
  728. X
  729. X  if ((p = rindex(buf, '\n')) != NULL)
  730. X    *p = '\0';
  731. X  if (strncmp("set ", buf, 4) == 0)
  732. X    {
  733. X      buf += 4;
  734. X      setflag = 1;
  735. X      debug1("RcLine: '%s' is a set command\n", buf);
  736. X    }
  737. X  else if (strncmp("se ", buf, 3) == 0)
  738. X    {
  739. X      buf += 3;
  740. X      setflag = 1;
  741. X      debug1("RcLine: '%s' is a se command\n", buf);
  742. X    }
  743. X  else
  744. X    {
  745. X      setflag = 0;
  746. X      debug1("RcLine: '%s'\n", buf);
  747. X    }
  748. X  if ((argc = Parse(buf, ap)) == 0)
  749. X    {
  750. X      if (setflag)
  751. X    {
  752. X      DeadlyMsg = 0;
  753. X      Msg(0, "%s: set what?\n", rc_name);
  754. X    }
  755. X      return;
  756. X    }
  757. X
  758. X  low = 0;
  759. X  high = (int)RC_RCEND - 1;
  760. X  while (low <= high)
  761. X    {
  762. X      mid = (low + high) / 2;
  763. X      x = strcmp(ap[0], RCNames[mid]);
  764. X      if (x < 0)
  765. X        high = mid - 1;
  766. X      else if (x > 0)
  767. X        low = mid + 1;
  768. X      else
  769. X        break;
  770. X    }
  771. X  if (low > high)
  772. X    mid = (int)RC_RCEND;
  773. X  switch ((enum RCcases) mid)
  774. X    {
  775. X    case RC_ESCAPE:
  776. X      if (argc != 2 || !ParseEscape(ap[1]))
  777. X    {
  778. X      DeadlyMsg = 0; 
  779. X      Msg(0, "%s: two characters required after escape.", rc_name);
  780. X      return;
  781. X    }
  782. X      if (Esc != MetaEsc)
  783. X    ktab[Esc].type = KEY_OTHER;
  784. X      else
  785. X    ktab[Esc].type = KEY_IGNORE;
  786. X      return;
  787. X    case RC_CHDIR:
  788. X      if (setflag)
  789. X    break;
  790. X      p = argc < 2 ? home : ap[1];
  791. X      if (chdir(p) == -1)
  792. X    {
  793. X      DeadlyMsg = 0; 
  794. X      Msg(errno, "%s", p);
  795. X    }
  796. X      return;
  797. X    case RC_SHELL:
  798. X      if (argc != 2)
  799. X    {
  800. X      DeadlyMsg = 0; 
  801. X      Msg(0, "%s: shell: one argument required.", rc_name);
  802. X      return;
  803. X    }
  804. X      ShellProg = ShellArgs[0] = SaveStr(ap[1]);
  805. X      return;
  806. X    case RC_SHELLAKA:
  807. X      if (argc != 2)
  808. X    {
  809. X      DeadlyMsg = 0; 
  810. X      Msg(0, "%s: shellaka: one argument required.", rc_name);
  811. X      return;
  812. X    }
  813. X      shellaka = SaveStr(ap[1]);
  814. X      return;
  815. X    case RC_SCREEN:
  816. X      if (setflag)
  817. X    break;
  818. X      DoScreen(rc_name, ap + 1);
  819. X      return;
  820. X    case RC_SLEEP:
  821. X    case RC_TERMCAP:
  822. X    case RC_TERMINFO:
  823. X      return;            /* Already handled */
  824. X    case RC_TERM:
  825. X      if ((argc != 2) || ((unsigned)strlen(args[1]) >= 20))
  826. X    {
  827. X      DeadlyMsg = 0;
  828. X      Msg(0,"%s: term: one argument required.", rc_name);
  829. X      return;
  830. X    }
  831. X      strcpy(screenterm, args[1]);
  832. X      debug1("screenterm set to %s\n", screenterm);
  833. X      MakeTermcap(0);
  834. X      return;    
  835. X    case RC_ECHO:
  836. X      if (HasWindow && *rc_name == '\0')
  837. X    {
  838. X      /*
  839. X       * user typed ^A:echo... well, echo isn't FinishRc's job,
  840. X       * but as he wanted to test us, we show good will
  841. X       */
  842. X      DeadlyMsg = 0;
  843. X      if (argc == 2 || (argc == 3 && !strcmp(ap[1], "-n")))
  844. X        Msg(0, "%s", ap[argc - 1]);
  845. X      else
  846. X         Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
  847. X    }
  848. X      return;
  849. X    case RC_BELL:
  850. X      if (argc != 2)
  851. X    {
  852. X      DeadlyMsg = 0; 
  853. X      Msg(0, "%s: bell: one argument required.", rc_name);
  854. X      return;
  855. X    }
  856. X      if (BellString)
  857. X    Free(BellString);
  858. X      BellString = SaveStr(ap[1]);
  859. X      return;
  860. X    case RC_ACTIVITY:
  861. X      if (argc != 2)
  862. X    {
  863. X      DeadlyMsg = 0; 
  864. X      Msg(0, "%s: activity: one argument required.", rc_name);
  865. X      return;
  866. X    }
  867. X      if (ActivityString)
  868. X    Free(ActivityString);
  869. X      ActivityString = SaveStr(ap[1]);
  870. X      return;
  871. X    case RC_POW_DETACH_MSG:
  872. X      if (argc != 2)
  873. X    {
  874. X      DeadlyMsg = 0;
  875. X      Msg(0, "%s: pow_detach: one argument required.", rc_name);
  876. X      return;
  877. X    }
  878. X      if (PowDetachString)
  879. X        Free(PowDetachString);
  880. X      PowDetachString = SaveStr(ap[1]);
  881. X      return;
  882. X    case RC_LOGIN:
  883. X#ifdef UTMPOK
  884. X      q = loginflag;
  885. X      ParseOnOff(argc, ap, &loginflag);
  886. X      if (fore && setflag)
  887. X    {
  888. X      SlotToggle(loginflag?(1):(-1));
  889. X      loginflag = q;
  890. X    }
  891. X#endif
  892. X      return;
  893. X    case RC_FLOW:
  894. X      if (argc == 3 && ap[2][0] == 'i')
  895. X    {
  896. X      iflag = 1;
  897. X      argc--;
  898. X    }
  899. X      if (argc == 2 && ap[1][0] == 'a')
  900. X    flowctl = 3;
  901. X      else
  902. X    {
  903. X      ParseOnOff(argc, ap, &flowctl);
  904. X      flowctl++;
  905. X    }
  906. X      return;
  907. X    case RC_WRAP:
  908. X      ParseOnOff(argc, ap, &wrap);
  909. X      return;
  910. X    case RC_HARDSTATUS:
  911. X      ParseOnOff(argc, ap, &use_hardstatus);
  912. X      if (use_hardstatus)
  913. X    HS = termcapHS;
  914. X      else
  915. X    HS = 0;
  916. X      return;
  917. X    case RC_MONITOR:
  918. X    {
  919. X      int f; 
  920. X
  921. X      ParseOnOff(argc, ap, &f);
  922. X      if (fore && setflag)
  923. X        fore->monitor = (f == 0) ? MON_OFF : MON_ON;
  924. X      else
  925. X        default_monitor = (f == 0) ? MON_OFF : MON_ON;
  926. X    }
  927. X      return;
  928. X    case RC_VBELL:
  929. X    case RC_VISUALBELL:
  930. X      ParseOnOff(argc, ap, &visual_bell);
  931. X      return;
  932. X    case RC_VBELLWAIT:
  933. X      ParseNum(argc, ap, &VBellWait);
  934. X      if (fore && rc_name[0] == '\0')
  935. X        Msg(0, "vbellwait set to %d seconds", VBellWait);
  936. X      return;
  937. X    case RC_MSGWAIT:
  938. X      ParseNum(argc, ap, &MsgWait);
  939. X      if (fore && rc_name[0] == '\0')
  940. X        Msg(0, "msgwait set to %d seconds", MsgWait);
  941. X      return;
  942. X    case RC_MSGMINWAIT:
  943. X      ParseNum(argc, ap, &MsgMinWait);
  944. X      if (fore && rc_name[0] == '\0')
  945. X        Msg(0, "msgminwait set to %d seconds", MsgMinWait);
  946. X      return;
  947. X    case RC_SCROLLBACK:
  948. X      if (fore && setflag)
  949. X    {
  950. X      int i;
  951. X
  952. X      ParseNum(argc, ap, &i);
  953. X      ChangeScrollback(fore, i, fore->width);
  954. X      if (fore && rc_name[0] == '\0')
  955. X        Msg(0, "scrollback set to %d", fore->histheight);
  956. X    }
  957. X      else
  958. X    ParseNum(argc, ap, &default_histheight);
  959. X      return;
  960. X    case RC_SLOWPASTE:
  961. X      ParseNum(argc, ap, &slowpaste);
  962. X      if (fore && rc_name[0] == '\0')
  963. X    Msg(0, "slowpaste set to %d milliseconds", slowpaste);
  964. X      return;
  965. X    case RC_MARKKEYS:
  966. X      if (argc != 2)
  967. X    {
  968. X      DeadlyMsg = 0;
  969. X      Msg(0, "%s: markkeys: one argument required.", rc_name);
  970. X      return;
  971. X    }
  972. X      if (CompileKeys(ap[1], mark_key_tab))
  973. X    {
  974. X      DeadlyMsg = 0;
  975. X      Msg(0, "%s: markkeys: syntax error.", rc_name);
  976. X      return;
  977. X    }
  978. X      debug1("markkeys %s\n", ap[1]);
  979. X      return;
  980. X#ifdef NETHACK
  981. X    case RC_NETHACK:
  982. X      ParseOnOff(argc, ap, &nethackflag);
  983. X      return;
  984. X#endif
  985. X    case RC_VBELL_MSG:
  986. X    case RC_VISUALBELL_MSG:
  987. X      if (argc != 2)
  988. X    {
  989. X      DeadlyMsg = 0;
  990. X      Msg(0, "%s: vbell_msg: one argument required.", rc_name);
  991. X      return;
  992. X    }
  993. X      if (VisualBellString)
  994. X    Free(VisualBellString);
  995. X      VisualBellString = SaveStr(ap[1]);
  996. X      debug1(" new vbellstr '%s'\n", VisualBellString);
  997. X      return;
  998. X    case RC_MODE:
  999. X      if (argc != 2)
  1000. X    {
  1001. X      DeadlyMsg = 0; 
  1002. X      Msg(0, "%s: mode: one argument required.", rc_name);
  1003. X      return;
  1004. X    }
  1005. X      if (!IsNum(ap[1], 7))
  1006. X    {
  1007. X      DeadlyMsg = 0; 
  1008. X      Msg(0, "%s: mode: octal number expected.", rc_name);
  1009. X      return;
  1010. X    }
  1011. X      (void) sscanf(ap[1], "%o", &TtyMode);
  1012. X      return;
  1013. X    case RC_CRLF:
  1014. X      ParseOnOff(argc, ap, &join_with_cr);
  1015. X      return;
  1016. X    case RC_AUTODETACH:
  1017. X      ParseOnOff(argc, ap, &auto_detach);
  1018. X      return;
  1019. X    case RC_STARTUP_MESSAGE:
  1020. X      ParseOnOff(argc, ap, &default_startup);
  1021. X      return;
  1022. X#ifdef PASSWORD
  1023. X    case RC_PASSWORD:
  1024. X      CheckPassword = 1;
  1025. X      if (argc >= 2)
  1026. X    {
  1027. X      strncpy(Password, ap[1], sizeof Password);
  1028. X      if (!strcmp(Password, "none"))
  1029. X        CheckPassword = 0;
  1030. X    }
  1031. X      else
  1032. X    {
  1033. X      char *mstr = 0;
  1034. X      int msleep = 0, st;
  1035. X          char salt[2];
  1036. X
  1037. X      /* there is a clear screen sequence in the buffer. */
  1038. X      fflush(stdout);
  1039. X      if (HasWindow)
  1040. X        {
  1041. X              ClearDisplay();
  1042. X          SetTTY(0, &OldMode);
  1043. X        }
  1044. X      strncpy(Password, getpass("New screen password:"),
  1045. X          sizeof(Password));
  1046. X      if (strcmp(Password, getpass("Retype new password:")))
  1047. X        {
  1048. X#ifdef NETHACK
  1049. X              if (nethackflag)
  1050. X            mstr = "[ Passwords don't match - your armor crumbles away ]";
  1051. X          else
  1052. X#endif
  1053. X          mstr = "[ Passwords don't match - checking turned off ]";
  1054. X          msleep = 1;
  1055. X          CheckPassword = 0;
  1056. X        }
  1057. X      if (Password[0] == '\0')
  1058. X        {
  1059. X          CheckPassword = 0;
  1060. X          mstr = "[ No password - no secure ]";
  1061. X          msleep = 1;
  1062. X        }
  1063. X      for (st=0; st<2; st++)
  1064. X            salt[st] = 'A' + (int)((time(0) >> 6*st) % 26);
  1065. X      strncpy(Password, crypt(Password, salt), sizeof(Password));
  1066. X      if (CheckPassword)
  1067. X        {
  1068. X#ifdef COPY_PASTE
  1069. X          if (copybuffer)
  1070. X
  1071. X        Free(copybuffer);
  1072. X          copylen = strlen(Password);
  1073. X          if ((copybuffer = (char *) malloc(copylen+1)) == NULL)
  1074. X        {
  1075. X          Msg_nomem;
  1076. X          return;
  1077. X        }
  1078. X          strcpy(copybuffer, Password);
  1079. X          mstr = "[ Password moved into copybuffer ]";
  1080. X          msleep = 1;
  1081. X#else                /* COPY_PASTE */
  1082. X          mstr = "[ Crypted password is \"%s\" ]";
  1083. X          msleep = 4;
  1084. X#endif                /* COPY_PASTE */
  1085. X        }
  1086. X          if (HasWindow)
  1087. X        {
  1088. X          SetTTY(0, &NewMode);
  1089. X          Activate(); /* Redraw */
  1090. X          if (mstr)
  1091. X            {
  1092. X              Msg(0, mstr, Password);
  1093. X            }
  1094. X        }
  1095. X          else
  1096. X        {
  1097. X          if (mstr)
  1098. X            {
  1099. X              printf(mstr, Password);
  1100. X              putchar('\n');
  1101. X              sleep(msleep);
  1102. X            }
  1103. X              ClearDisplay();
  1104. X        }
  1105. X    }
  1106. X      debug1("finishrc: our password is: --%s%-- \n", Password);
  1107. X      return;
  1108. X#endif                /* PASSWORD */
  1109. X    case RC_ALL:
  1110. X      if (!setflag || !HasWindow || *rc_name)
  1111. X        break;
  1112. X      display_help();
  1113. X      return;
  1114. X    case RC_BIND:
  1115. X      if (setflag)
  1116. X    break;
  1117. X      p = ap[1];
  1118. X      if (argc < 2 || *p == '\0')
  1119. X    {
  1120. X      DeadlyMsg = 0; 
  1121. X      Msg(0, "%s: key expected after bind.", rc_name);
  1122. X      return;
  1123. X    }
  1124. X      if ((p = ParseChar(p, &key)) == NULL || *p)
  1125. X    {
  1126. X      DeadlyMsg = 0; 
  1127. X      Msg(0, "%s: bind: character, ^x, or (octal) \\032 expected.",
  1128. X          rc_name);
  1129. X      return;
  1130. X    }
  1131. X      if (ktab[key].type != KEY_IGNORE)
  1132. X    {
  1133. X      ktab[key].type = KEY_IGNORE;
  1134. X      if ((pp = ktab[key].args) != NULL)
  1135. X        {
  1136. X          for (; *pp; pp++)
  1137. X        Free(*pp);
  1138. X          Free(ktab[key].args);
  1139. X        }
  1140. X    }
  1141. X      if (argc > 2)
  1142. X    {
  1143. X      for (pp = KeyNames; *pp; ++pp)
  1144. X        if (strcmp(ap[2], *pp) == 0)
  1145. X          break;
  1146. X      if (*pp)
  1147. X        {
  1148. X          ktab[key].type = (enum keytype) (pp - KeyNames + 1);
  1149. X          if (argc > 3)
  1150. X        {
  1151. X          ktab[key].args = SaveArgs(argc - 3, ap + 3);
  1152. X        }
  1153. X          else
  1154. X        ktab[key].args = NULL;
  1155. X        }
  1156. X      else
  1157. X        {
  1158. X          ktab[key].type = KEY_CREATE;
  1159. X          ktab[key].args = SaveArgs(argc - 2, ap + 2);
  1160. X        }
  1161. X    }
  1162. X      return;
  1163. X    case RC_RCEND:
  1164. X    default:
  1165. X    {
  1166. X      char ibuf[3];
  1167. X      /*
  1168. X       * now we are user-friendly: 
  1169. X       * if anyone typed a key name like "help" or "next" ...
  1170. X       * we did not match anything above. so look in the KeyNames table.
  1171. X       */
  1172. X      debug1("--ap[0] %s\n", ap[0]);
  1173. X      for (pp = KeyNames; *pp; ++pp)
  1174. X        if (strcmp(ap[0], *pp) == 0)
  1175. X        break;
  1176. X      if (*pp == 0)
  1177. X        break;
  1178. X
  1179. X      ibuf[0] = Esc;
  1180. X      ibuf[1] = pp - KeyNames +1;
  1181. X      debug1("RcLine: it was a keyname: '%s'\n", *pp);
  1182. X      q = 2; qq = 0;
  1183. X      if (HasWindow)
  1184. X        ProcessInput(ibuf, &q, (char *)0, &qq, 0);
  1185. X      else
  1186. X        {
  1187. X          DeadlyMsg = 0; 
  1188. X          Msg(0, "%s: Key '%s' has no effect while no window open...\n",
  1189. X              rc_name, ap[0]);
  1190. X        }
  1191. X    }
  1192. X      return;
  1193. X    }
  1194. X  DeadlyMsg = 0; 
  1195. X  Msg(0, "%s: unknown %skeyword \"%s\"", rc_name, 
  1196. X      setflag?"'set' ":"", ap[0]);
  1197. X}
  1198. X
  1199. static int Parse(buf, args)
  1200. char *buf, **args;
  1201. X{
  1202. X  register char *p = buf, **ap = args;
  1203. X  register int delim, argc;
  1204. X
  1205. X  argc = 0;
  1206. X  for (;;)
  1207. X    {
  1208. X      while (*p && (*p == ' ' || *p == '\t'))
  1209. X    ++p;
  1210. X      if (*p == '\0' || *p == '#')
  1211. X    {
  1212. X      *p = '\0';
  1213. X      return argc;
  1214. X    }
  1215. X      if (argc > MAXARGS - 1)
  1216. X    Msg(0, "%s: too many tokens.", rc_name);
  1217. X      delim = 0;
  1218. X      if (*p == '"' || *p == '\'')
  1219. X    delim = *p++;
  1220. X      argc++;
  1221. X      *ap = p;
  1222. X      *++ap = 0;
  1223. X      while (*p && !(delim ? *p == delim : (*p == ' ' || *p == '\t')))
  1224. X    ++p;
  1225. X      if (*p == '\0')
  1226. X    {
  1227. X      if (delim)
  1228. X        {
  1229. X          DeadlyMsg = 0;
  1230. X          Msg(0, "%s: Missing quote.", rc_name);
  1231. X          return 0;
  1232. X    }
  1233. X      return argc;
  1234. X    }
  1235. X      *p++ = '\0';
  1236. X    }
  1237. X}
  1238. X
  1239. int ParseEscape(p)
  1240. char *p;
  1241. X{
  1242. X  if ((p = ParseChar(p, &Esc)) == NULL ||
  1243. X      (p = ParseChar(p, &MetaEsc)) == NULL || *p)
  1244. X    return 0;
  1245. X  return 1;
  1246. X}
  1247. X
  1248. void
  1249. ParseNum(argc, ap, var)
  1250. int argc;
  1251. char *ap[];
  1252. int *var;
  1253. X{
  1254. X  int i;
  1255. X  char *p;
  1256. X
  1257. X  if (argc == 2 && ap[1][0] != '\0')
  1258. X    {
  1259. X      i = 0; 
  1260. X      p = ap[1];
  1261. X      while (*p)
  1262. X    {
  1263. X      if (*p >= '0' && *p <= '9')
  1264. X        i = 10 * i + (*p - '0');
  1265. X      else
  1266. X        {
  1267. X          DeadlyMsg = 0;
  1268. X          Msg(0, "%s: %s: invalid argument. Give numeric argument",
  1269. X          rc_name, ap[0]);
  1270. X          return;
  1271. X        }    
  1272. X      p++;
  1273. X    }
  1274. X    }
  1275. X  else
  1276. X    {
  1277. X      DeadlyMsg = 0;
  1278. X      Msg(0, "%s: %s: invalid argument. Give one argument",
  1279. X          rc_name, ap[0]);
  1280. X      return;
  1281. X    }
  1282. X  debug1("ParseNum got %d\n", i);
  1283. X  *var = i;
  1284. X}
  1285. X
  1286. void
  1287. ParseOnOff(argc, ap, var)
  1288. int argc;
  1289. char *ap[];
  1290. int *var;
  1291. X{
  1292. X  register int num = -1;
  1293. X
  1294. X  if (argc == 2 && ap[1][0] == 'o')
  1295. X    {
  1296. X      if (ap[1][1] == 'f')
  1297. X    num = 0;
  1298. X      else if (ap[1][1] == 'n')
  1299. X    num = 1;
  1300. X    }
  1301. X  if (num < 0)
  1302. X    {
  1303. X      DeadlyMsg = 0;
  1304. X      Msg(0, "%s: %s: invalid argument. Give 'on' or 'off'", rc_name, ap[0]);
  1305. X      return;
  1306. X    }
  1307. X  *var = num;
  1308. X}
  1309. X
  1310. X
  1311. static int IsNum(s, base)
  1312. register char *s;
  1313. register int base;
  1314. X{
  1315. X  for (base += '0'; *s; ++s)
  1316. X    if (*s < '0' || *s > base)
  1317. X      return 0;
  1318. X  return 1;
  1319. X}
  1320. X
  1321. static int IsNumColon(s, base, p)
  1322. int base;
  1323. char *s, *p;
  1324. X{
  1325. X  char *q;
  1326. X  if ((q = rindex(s, ':')) != NULL)
  1327. X    {
  1328. X      strncpy(p, q + 1, 19);
  1329. X      *q = '\0';
  1330. X    }
  1331. X  else
  1332. X    *p = '\0';
  1333. X  return IsNum(s, base);
  1334. X}
  1335. X
  1336. void
  1337. SlotToggle(how)
  1338. int how;
  1339. X/*
  1340. X * how = 0    real toggle mode
  1341. X * how > 0    do try to set a utmp slot.
  1342. X * how < 0    try to withdraw a utmp slot
  1343. X *
  1344. X * slot = -1    window not logged in.
  1345. X * slot = 0     window not logged in, but should be logged in. 
  1346. X *              (unable to write utmp, or detached).
  1347. X */
  1348. X{
  1349. X  debug1("SlotToggle %d\n", how);
  1350. X  if (how == 0)
  1351. X    how = (fore->slot == (slot_t) -1)?(1):(-1);
  1352. X    /* 
  1353. X     * slot 0 or active -> we try to log out.
  1354. X     * slot -1          -> we try to log in.
  1355. X     */
  1356. X#ifdef UTMPOK
  1357. X  if (how > 0)
  1358. X    {
  1359. X      debug(" try to log in\n");
  1360. X      if ((fore->slot == (slot_t) -1) || (fore->slot == (slot_t) 0))
  1361. X    {
  1362. X#ifdef USRLIMIT
  1363. X          if (CountUsers() >= USRLIMIT)
  1364. X            Msg(0, "User limit reached.");
  1365. X          else
  1366. X#endif
  1367. X            {
  1368. X              if (SetUtmp(fore, ForeNum) == 0)
  1369. X                Msg(0, "This window is now logged in.");
  1370. X              else
  1371. X                Msg(0, "This window should now be logged in.");
  1372. X            }
  1373. X    }
  1374. X      else
  1375. X    Msg(0, "This window is already logged in.");
  1376. X    }
  1377. X  else if (how < 0)
  1378. X    {
  1379. X      debug(" try to log out\n");
  1380. X      if (fore->slot == (slot_t) -1)
  1381. X    Msg(0, "This window is already logged out\n");
  1382. X      else if (fore->slot == (slot_t) 0)
  1383. X    {
  1384. X      debug("What a relief! In fact, it was not logged in\n");
  1385. X      Msg(0, "This window is not logged in.");
  1386. X      fore->slot = (slot_t) -1;
  1387. X    }
  1388. X      else
  1389. X    {
  1390. X      RemoveUtmp(fore);
  1391. X      if (fore->slot != (slot_t) -1)
  1392. X        Msg(0, "What? Cannot remove Utmp slot?");
  1393. X      else
  1394. X        Msg(0, "This window is no longer logged in.");
  1395. X    }
  1396. X    }
  1397. X#else    /* !UTMPOK */
  1398. X  Msg(0, "Unable to modify /etc/utmp.\n");
  1399. X#endif
  1400. X}
  1401. X
  1402. void
  1403. DoScreen(fn, av)
  1404. char *fn, **av;
  1405. X{
  1406. X  register int flowflag, num, lflag = loginflag;
  1407. X  register char *aka = NULL;
  1408. X  register int histheight = default_histheight;
  1409. X  char buf[20];
  1410. X  char termbuf[25];
  1411. X  char *termp;
  1412. X  char *args[2];
  1413. X
  1414. X  flowflag = flowctl;
  1415. X  termbuf[0] = '\0';
  1416. X  termp = NULL;
  1417. X  while (av && *av && av[0][0] == '-')
  1418. X    {
  1419. X      switch (av[0][1])
  1420. X    {
  1421. X    case 'f':
  1422. X      switch (av[0][2])
  1423. X        {
  1424. X        case 'n':
  1425. X        case '0':
  1426. X          flowflag = 1;
  1427. X          break;
  1428. X        case 'y':
  1429. X        case '1':
  1430. X        case '\0':
  1431. X          flowflag = 2;
  1432. X          break;
  1433. X        case 'a':
  1434. X          flowflag = 3;
  1435. X          break;
  1436. X        default:
  1437. X          break;
  1438. X        }
  1439. X      break;
  1440. X    case 'k':
  1441. X    case 't':
  1442. X      if (av[0][2])
  1443. X        aka = &av[0][2];
  1444. X      else if (*++av)
  1445. X        aka = *av;
  1446. X      else
  1447. X        --av;
  1448. X      break;
  1449. X    case 'T':
  1450. X      if (av[0][2])
  1451. X        termp = &av[0][2];
  1452. X      else if (*++av)
  1453. X        termp = *av;
  1454. X      else
  1455. X        --av;
  1456. X      break;
  1457. X    case 'h':
  1458. X      if (av[0][2])
  1459. X        histheight = atoi(av[0] + 2);
  1460. X      else if (*++av)
  1461. X        histheight = atoi(*av);
  1462. X      else 
  1463. X        --av;
  1464. X      break;
  1465. X    case 'l':
  1466. X      switch (av[0][2])
  1467. X        {
  1468. X        case 'n':
  1469. X        case '0':
  1470. X          lflag = 0;
  1471. X          break;
  1472. X        case 'y':
  1473. X        case '1':
  1474. X        case '\0':
  1475. X          lflag = 1;
  1476. X          break;
  1477. X        default:
  1478. X          break;
  1479. X        }
  1480. X      break;
  1481. X    default:
  1482. X      Msg(0, "%s: screen: invalid option -%c.", fn, av[0][1]);
  1483. X      break;
  1484. X    }
  1485. X      ++av;
  1486. X    }
  1487. X  num = 0;
  1488. X  if (av && *av && IsNumColon(*av, 10, buf))
  1489. X    {
  1490. X      if (*buf != '\0')
  1491. X    aka = buf;
  1492. X      num = atoi(*av);
  1493. X      if (num < 0 || num > MAXWIN - 1)
  1494. X    Msg(0, "%s: illegal screen number %d.", fn, num);
  1495. X      ++av;
  1496. X    }
  1497. X  if (!av || !*av)
  1498. X    {
  1499. X      av = args;
  1500. X      av[0] = ShellProg;
  1501. X      av[1] = NULL;
  1502. X      if (!aka)
  1503. X    aka = shellaka;
  1504. X    }
  1505. X  MakeWindow(aka, av, 0, flowflag, num, (char *) 0, lflag, histheight, termp);
  1506. X}
  1507. X
  1508. void
  1509. WriteFile(dump)
  1510. int dump;
  1511. X{
  1512. X  /* dump==0:    create .termcap,
  1513. X   * dump==1:    hardcopy,
  1514. X   * #ifdef COPY_PASTE
  1515. X   * dump==2:    BUFFERFILE
  1516. X   * #endif COPY_PASTE 
  1517. X   */
  1518. X  register int i, j, k;
  1519. X  register char *p;
  1520. X  register FILE *f;
  1521. X  char fn[1024];
  1522. X
  1523. X  switch (dump)
  1524. X    {
  1525. X    case DUMP_TERMCAP:
  1526. X      i = SockNamePtr - SockPath;
  1527. X      strncpy(fn, SockPath, i);
  1528. X      strcpy(fn + i, ".termcap");
  1529. X      break;
  1530. X    case DUMP_HARDCOPY:
  1531. X      sprintf(fn, "hardcopy.%d", ForeNum);
  1532. X      break;
  1533. X    case DUMP_EXCHANGE:
  1534. X      sprintf(fn, "/tmp/%s", BUFFERFILE);
  1535. X      umask(0);
  1536. X      break;
  1537. X    }
  1538. X
  1539. X  debug2("WriteFile(%d) %s\n", dump, fn);
  1540. X  if (UserContext() > 0)
  1541. X    {
  1542. X      debug("Writefile: usercontext\n");
  1543. X      if ((f = fopen(fn, "w")) == NULL)
  1544. X    {
  1545. X      debug1("WriteFile: fopen(%s) failed\n", fn);
  1546. X      UserReturn(0);
  1547. X    }
  1548. X      else
  1549. X    {
  1550. X      switch (dump)
  1551. X        {
  1552. X        case DUMP_HARDCOPY:
  1553. X          for (i = 0; i < screenheight; ++i)
  1554. X        {
  1555. X          p = fore->image[i];
  1556. X          for (k = screenwidth - 1; k >= 0 && p[k] == ' '; --k)
  1557. X            ;
  1558. X          for (j = 0; j <= k; ++j)
  1559. X            putc(p[j], f);
  1560. X          putc('\n', f);
  1561. X        }
  1562. X          break;
  1563. X        case DUMP_TERMCAP:
  1564. X          if ((p = index(MakeTermcap(fore->aflag), '=')) != NULL)
  1565. X        {
  1566. X          fputs(++p, f);
  1567. X          putc('\n', f);
  1568. X        }
  1569. X          break;
  1570. X#ifdef COPY_PASTE
  1571. X        case DUMP_EXCHANGE:
  1572. X          p = copybuffer;
  1573. X          for (i = 0; i < copylen; i++)
  1574. X        putc(*p++, f);
  1575. X          break;
  1576. X#endif
  1577. X        }
  1578. X      (void) fclose(f);
  1579. X      UserReturn(1);
  1580. X    }
  1581. X    }
  1582. X  if (UserStatus() <= 0)
  1583. X    Msg(0, "Cannot open \"%s\"", fn);
  1584. X  else
  1585. X    {
  1586. X      switch (dump)
  1587. X    {
  1588. X    case DUMP_TERMCAP:
  1589. X      Msg(0, "Termcap entry written to \"%s\".", fn);
  1590. X      break;
  1591. X    case DUMP_HARDCOPY:
  1592. X      Msg(0, "Screen image written to \"%s\".", fn);
  1593. X      break;
  1594. X#ifdef COPY_PASTE
  1595. X    case DUMP_EXCHANGE:
  1596. X      Msg(0, "Copybuffer written to \"%s\".", fn);
  1597. X#endif
  1598. X    }
  1599. X    }
  1600. X}
  1601. X
  1602. X#ifdef COPY_PASTE
  1603. X
  1604. void
  1605. ReadFile()
  1606. X{
  1607. X  int i, l, size;
  1608. X  char fn[1024], c;
  1609. X  struct stat stb;
  1610. X
  1611. X  sprintf(fn, "/tmp/%s", BUFFERFILE);
  1612. X  debug1("ReadFile(%s)\n", fn);
  1613. X  if ((i = secopen(fn, O_RDONLY, 0)) < 0)
  1614. X    {
  1615. X      Msg(errno, "no %s -- no slurp", fn);
  1616. X      return;
  1617. X    }
  1618. X  if (fstat(i, &stb))
  1619. X    {
  1620. X      Msg(errno, "no good %s -- no slurp", fn);
  1621. X      close(i);
  1622. X      return;
  1623. X    }
  1624. X  size = stb.st_size;
  1625. X  if (copybuffer)
  1626. X    Free(copybuffer);
  1627. X  copylen = 0;
  1628. X  if ((copybuffer = malloc(size)) == NULL)
  1629. X    {
  1630. X      close(i);
  1631. X      Msg_nomem;
  1632. X      return;
  1633. X    }
  1634. X  errno = 0;
  1635. X  if ((l = read(i, copybuffer, size)) != size)
  1636. X    {
  1637. X      copylen = (l > 0) ? l : 0;
  1638. X#ifdef NETHACK
  1639. X      if (nethackflag)
  1640. X        Msg(errno, "You choke on your food: %d bytes", copylen);
  1641. X      else
  1642. X#endif
  1643. X      Msg(errno, "Got only %d bytes from %s", copylen, fn);
  1644. X      close(i);
  1645. X      return;
  1646. X    }
  1647. X  copylen = l;
  1648. X  if (read(i, &c, 1) > 0)
  1649. X    Msg(0, "Slurped only %d characters into buffer - try again", copylen);
  1650. X  else
  1651. X    Msg(0, "Slurped %d characters into buffer", copylen);
  1652. X  close(i);
  1653. X  return;
  1654. X}
  1655. X
  1656. void
  1657. KillBuffers()
  1658. X{
  1659. X  char fn[1024];
  1660. X  sprintf(fn, "/tmp/%s", BUFFERFILE);
  1661. X  errno = 0;
  1662. X  if (access(fn, W_OK) == -1)
  1663. X    {
  1664. X      Msg(errno, "%s not removed", fn);
  1665. X      return;
  1666. X    }
  1667. X  else
  1668. X    {
  1669. X      unlink(fn);
  1670. X      Msg(errno, "%s removed", fn);
  1671. X    }
  1672. X}
  1673. X#endif    /* COPY_PASTE */
  1674. X
  1675. X#ifdef USRLIMIT
  1676. CountUsers()
  1677. X{
  1678. X#ifdef GETUTENT
  1679. X  struct utmp *ut, *getutent();
  1680. X#else
  1681. X  struct utmp utmpbuf;
  1682. X#endif
  1683. X  int UserCount;
  1684. X
  1685. X  debug1("CountUsers() - utmp=%d\n",utmp);
  1686. X  if (!utmp)
  1687. X    return(0);
  1688. X  UserCount = 0;
  1689. X#ifdef GETUTENT
  1690. X  setutent();
  1691. X  while (ut = getutent())
  1692. X    if (ut->ut_type == USER_PROCESS)
  1693. X      UserCount++;
  1694. X#else
  1695. X  (void) lseek(utmpf, (off_t) 0, 0);
  1696. X  while (read(utmpf, &utmpbuf, sizeof(struct utmp)) > 0)
  1697. X    {
  1698. X      if (utmpbuf.ut_name[0] != '\0')
  1699. X       UserCount++;
  1700. X    }
  1701. X#endif
  1702. X  return(UserCount);
  1703. X}
  1704. X#endif
  1705. X
  1706. X#ifdef UTMPOK
  1707. X
  1708. static slot_t loginslot;
  1709. static struct utmp utmp_logintty;
  1710. X#ifdef _SEQUENT_
  1711. static char loginhost[100+1];
  1712. X#endif
  1713. X
  1714. void
  1715. InitUtmp()
  1716. X{
  1717. X  debug("InitUtmp testing...\n");
  1718. X  if ((utmpf = open(UtmpName, O_RDWR)) == -1)
  1719. X    {
  1720. X      if (errno != EACCES)
  1721. X    Msg(errno, UtmpName);
  1722. X      debug("InitUtmp failed.\n");
  1723. X      utmp = 0;
  1724. X      return;
  1725. X    }
  1726. X#ifdef GETUTENT
  1727. X  close(utmpf);
  1728. X  utmpf= -1;
  1729. X#endif
  1730. X#ifdef MIPS
  1731. X  if ((utmpfappend = open(UtmpName, O_APPEND)) == -1) 
  1732. X    {
  1733. X      if (errno != EACCES)
  1734. X    Msg(errno, UtmpName);
  1735. X      return;
  1736. X    }
  1737. X#endif
  1738. X  utmp = 1;
  1739. X  ReInitUtmp();
  1740. X}
  1741. X
  1742. void
  1743. ReInitUtmp()
  1744. X{
  1745. X  if (!utmp)
  1746. X    {
  1747. X      debug("Reinitutmp: utmp == 0\n");
  1748. X      return;
  1749. X    }
  1750. X  debug("(Re)InitUtmp: removing your logintty\n");
  1751. X  loginslot = TtyNameSlot(ttyname(0));
  1752. X  if (loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
  1753. X    {
  1754. X#ifdef _SEQUENT_
  1755. X      if (p=ut_find_host(loginslot))
  1756. X        strncpy(loginhost, p, 100);
  1757. X#endif
  1758. X      RemoveLoginSlot(loginslot, &utmp_logintty);
  1759. X    }
  1760. X  debug1(" slot %d zapped\n", loginslot);
  1761. X}
  1762. X
  1763. void
  1764. RestoreLoginSlot()
  1765. X{
  1766. X  debug("RestoreLoginSlot()\n");
  1767. X  if (utmp && loginslot!=(slot_t)0 && loginslot!=(slot_t)-1)
  1768. X    {
  1769. X#ifdef GETUTENT
  1770. X# ifdef _SEQUENT_
  1771. X      int fail;
  1772. X      debug1(" logging you in again (slot %s)\n", loginslot);
  1773. X/*
  1774. X * We have problems if we add the console and use ut_add_user()
  1775. X * because the id will be 'scon' instead of 'co'. So we
  1776. X * restore it with pututline(). The reason why we don't use
  1777. X * pututline all the time is that we want to set the host field.
  1778. X * Unfortunatelly this can only be done with ut_add_user().
  1779. X */
  1780. X      if (*loginhost)
  1781. X        {
  1782. X          fail = (ut_add_user(LoginName, loginslot, utmp_logintty.ut_pid,
  1783. X                              *loginhost?loginhost:(char *)0) == 0);
  1784. X        }
  1785. X      else
  1786. X        {
  1787. X          setutent();
  1788. X          fail = (pututline(&utmp_logintty) == 0);
  1789. X        }
  1790. X      if (fail)
  1791. X# else    /* _SEQUENT_ */
  1792. X      debug1(" logging you in again (slot %s)\n", loginslot);
  1793. X      setutent();
  1794. X      if (pututline(&utmp_logintty)==0)
  1795. X# endif    /* _SEQUENT */
  1796. X#else    /* GETUTENT */
  1797. X      debug1(" logging you in again (slot %d)\n", loginslot);
  1798. X# ifdef sequent
  1799. X      /* call sequent undocumented routine to count logins and add utmp entry if possible */
  1800. X      if (add_utmp(loginslot, &utmp_logintty) == -1)
  1801. X# else
  1802. X      (void) lseek(utmpf, (off_t) (loginslot * sizeof(struct utmp)), 0);
  1803. X      if (write(utmpf, (char *) &utmp_logintty, sizeof(struct utmp))
  1804. X      != sizeof(struct utmp))
  1805. X# endif /* sequent */
  1806. X#endif    /* GETUTENT */
  1807. X        {
  1808. X#ifdef NETHACK
  1809. X          if (nethackflag)
  1810. X            Msg(errno, "/etc/utmp is to hard to dig");
  1811. X      else
  1812. X#endif
  1813. X          Msg(errno,"Could not write /etc/utmp");
  1814. X        }
  1815. X    }
  1816. X  loginslot = (slot_t) 0;
  1817. X}
  1818. X
  1819. void
  1820. RemoveLoginSlot(slot, up)
  1821. slot_t slot;
  1822. struct utmp *up;
  1823. X{
  1824. X#ifdef GETUTENT
  1825. X  struct utmp *uu;
  1826. X#endif
  1827. X  struct utmp u;
  1828. X
  1829. X#ifdef GETUTENT
  1830. X  debug2("RemoveLoginSlot(%s, %08x)\n", (slot == (slot_t) 0 ||
  1831. X         slot == (slot_t) -1 ) ? "no slot" : slot, up);
  1832. X#else
  1833. X  debug2("RemoveLoginSlot(%d, %08x)\n", slot, up);
  1834. X#endif
  1835. X  if (!utmp)
  1836. X    return;
  1837. X  if (slot != (slot_t) 0 && slot != (slot_t) -1)
  1838. X    {
  1839. X      bzero((char *) &u, sizeof u);
  1840. X#ifdef GETUTENT
  1841. X      setutent();
  1842. X      strncpy(u.ut_line, slot, sizeof(u.ut_line));
  1843. X      if ((uu = getutline(&u)) == 0)
  1844. X        {
  1845. X      DeadlyMsg = 0;
  1846. X          Msg(0, "Utmp slot not found -> not removed");
  1847. X          return;
  1848. X        }
  1849. X      *up= *uu;
  1850. X# ifdef _SEQUENT_
  1851. X      if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  1852. X# else
  1853. X      uu->ut_type = DEAD_PROCESS;
  1854. X      uu->ut_exit.e_termination = 0;
  1855. X      uu->ut_exit.e_exit= 0;
  1856. X      if (pututline(uu) == 0)
  1857. X# endif
  1858. X#else
  1859. X      (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1860. X      if (read(utmpf, (char *) up, sizeof u) != sizeof u)
  1861. X    {
  1862. X      DeadlyMsg = 0;
  1863. X      Msg(errno, "cannot read /etc/utmp ???");
  1864. X      sleep(1);
  1865. X    }
  1866. X      (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  1867. X      if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  1868. X#endif
  1869. X        {
  1870. X#ifdef NETHACK
  1871. X          if (nethackflag)
  1872. X        {
  1873. X          DeadlyMsg = 0;
  1874. X              Msg(errno, "/etc/utmp is to hard to dig");
  1875. X        }
  1876. X          else
  1877. X#endif
  1878. X        {
  1879. X          DeadlyMsg = 0;
  1880. X              Msg(errno,"Could not write /etc/utmp");
  1881. X        }
  1882. X        }
  1883. X    }
  1884. X  else 
  1885. X    {
  1886. X      debug1("There is no utmp-slot to be removed(%d)\n", slot);
  1887. X    }
  1888. X}
  1889. X
  1890. static char *stripdev(nam)
  1891. char *nam;
  1892. X{
  1893. X  if (nam == 0)
  1894. X    return(0);
  1895. X  if (strncmp(nam, "/dev/", 5) == 0)
  1896. X    return(nam + 5);
  1897. X  return(nam);
  1898. X}
  1899. X
  1900. static slot_t TtyNameSlot(nam)
  1901. char *nam;
  1902. X{
  1903. X  char *name;
  1904. X  register slot_t slot;
  1905. X#ifndef GETUTENT
  1906. X  register struct ttyent *tp;
  1907. X#endif
  1908. X
  1909. X  debug1("TtyNameSlot(%s)\n", nam);
  1910. X  if (!utmp || nam == NULL)
  1911. X    return (slot_t)0;
  1912. X  name = stripdev(nam);
  1913. X#ifdef GETUTENT
  1914. X  slot = name;
  1915. X#else
  1916. X  slot = 1;
  1917. X  setttyent();
  1918. X  while ((tp = getttyent()) != NULL && strcmp(name, tp->ty_name) != 0)
  1919. X    {
  1920. X      debug2("'%s' %d, ", tp->ty_name, slot);
  1921. X      ++slot;
  1922. X    }
  1923. X  debug("\n");
  1924. X# ifdef MIPS
  1925. X  if (tp == NULL)
  1926. X    {
  1927. X      slot = CreateUtmp(name);
  1928. X    }
  1929. X# endif /* MIPS */
  1930. X#endif
  1931. X  return slot;
  1932. X}
  1933. X
  1934. int
  1935. SetUtmp(wi, displaynumber)
  1936. struct win *wi;
  1937. int displaynumber;
  1938. X{
  1939. X  register char *p;
  1940. X  register slot_t slot;
  1941. X  char *line;
  1942. X  struct utmp u;
  1943. X#ifdef UTHOST
  1944. X# ifdef _SEQUENT_
  1945. X  char host[100+5];
  1946. X# else
  1947. X  char host[sizeof(utmp_logintty.ut_host)+5];
  1948. X# endif
  1949. X#endif
  1950. X
  1951. X  wi->slot = (slot_t) 0;
  1952. X  if (!utmp)
  1953. X    return -1;
  1954. X  if ((slot = TtyNameSlot(wi->tty)) == (slot_t) NULL)
  1955. X    {
  1956. X      debug1("SetUtmp failed (tty %s).\n",wi->tty);
  1957. X      return -1;
  1958. X    }
  1959. X  debug2("SetUtmp %d will get slot %d...\n", displaynumber, (int)slot);
  1960. X
  1961. X#ifdef UTHOST
  1962. X  host[sizeof(host)-5] = '\0';
  1963. X# ifdef _SEQUENT_
  1964. X  strncpy(host, loginhost, sizeof(host) - 5);
  1965. X# else
  1966. X  strncpy(host, utmp_logintty.ut_host, sizeof(host) - 5);
  1967. X# endif
  1968. X  if (loginslot != (slot_t)0 && loginslot != (slot_t)-1 && host[0] != '\0')
  1969. X    {
  1970. X      /*
  1971. X       * we want to set our ut_host field to something like
  1972. X       * ":ttyhf:s.0" or
  1973. X       * "faui45:s.0" or
  1974. X       * "132.199.81.4:s.0" but not
  1975. X       * "faui45.informati"......:s.0
  1976. X       */
  1977. X      for (p = host; *p; p++)
  1978. X    {
  1979. X      if ((*p < '0' || *p > '9') && (*p != '.'))
  1980. X        break;
  1981. X    }
  1982. X      if (*p)
  1983. X    {
  1984. X      for (p = host; *p; p++)
  1985. X        {
  1986. X          if (*p == '.')
  1987. X        {
  1988. X          *p = '\0';
  1989. X          break;
  1990. X        }
  1991. X        }
  1992. X    }
  1993. X    }
  1994. X  else
  1995. X    {
  1996. X      strncpy(host + 1, stripdev(ttyname(0)), sizeof(host) - 6);
  1997. X      host[0] = ':';
  1998. X    }
  1999. X  debug1("rlogin hostname: '%s'\n", host);
  2000. X  sprintf(host + strlen(host), ":S.%c", '0' + displaynumber);
  2001. X  debug1("rlogin hostname: '%s'\n", host);
  2002. X#endif /* UTHOST */
  2003. X
  2004. X  line = stripdev(wi->tty);
  2005. X  bzero((char *) &u, sizeof u);
  2006. X#ifdef GETUTENT
  2007. X# ifdef _SEQUENT_
  2008. X  if (ut_add_user(LoginName, slot, wi->wpid, host)==0)
  2009. X# else
  2010. X  strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
  2011. X  strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
  2012. X  strncpy(u.ut_line, line, sizeof(u.ut_line));
  2013. X  u.ut_pid = wi->wpid;
  2014. X  u.ut_type = USER_PROCESS;
  2015. X  (void) time(&u.ut_time);
  2016. X#  ifdef UTHOST
  2017. X  strncpy(u.ut_host, host, sizeof(u.ut_host));
  2018. X#  endif /* UTHOST */
  2019. X  if (pututline(&u) == 0)
  2020. X# endif /* _SEQUENT_ */
  2021. X#else    /* GETUTENT */
  2022. X  strncpy(u.ut_line, line, sizeof(u.ut_line));
  2023. X  strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
  2024. X# ifdef UTHOST
  2025. X  strncpy(u.ut_host, host, sizeof(u.ut_host));
  2026. X# endif    /* UTHOST */
  2027. X# ifdef MIPS
  2028. X  u.ut_type = 7; /* USER_PROCESS */
  2029. X  strncpy(u.ut_id, line + 3, 4);
  2030. X# endif /* MIPS */
  2031. X  (void) time(&u.ut_time);
  2032. X# ifdef sequent
  2033. X/* call sequent undocumented routine to count logins and add utmp entry if possible */
  2034. X  if (add_utmp(slot, &u) == -1)
  2035. X# else
  2036. X  (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  2037. X  if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  2038. X# endif /* sequent */
  2039. X#endif    /* GETUTENT */
  2040. X    {
  2041. X#ifdef NETHACK
  2042. X      if (nethackflag)
  2043. X        Msg(errno, "/etc/utmp is to hard to dig");
  2044. X      else
  2045. X#endif
  2046. X      Msg(errno,"Could not write /etc/utmp");
  2047. X      return -1;
  2048. X    }
  2049. X  debug("SetUtmp successful\n");
  2050. X  wi->slot = slot;
  2051. X  return 0;
  2052. X}
  2053. X
  2054. X#ifdef MIPS
  2055. X
  2056. X#define GETTTYENT
  2057. static int ttyfd = 0;
  2058. X
  2059. static void setttyent()
  2060. X{
  2061. X  if (ttyfd)
  2062. X    close(ttyfd);
  2063. X  ttyfd = open(UtmpName, O_RDONLY);
  2064. X}
  2065. X
  2066. static struct ttyent *getttyent()
  2067. X{
  2068. X  static struct utmp u;
  2069. X  static struct ttyent t;
  2070. X
  2071. X  if (!ttyfd)
  2072. X    return NULL;
  2073. X  
  2074. X  if (read(ttyfd, &u, sizeof u)) 
  2075. X    {
  2076. X      t.ty_name = u.ut_line;
  2077. X      return &t;
  2078. X    }
  2079. X  return NULL;
  2080. X}
  2081. X
  2082. CreateUtmp(name)
  2083. char *name;
  2084. X{
  2085. X  int slot;
  2086. X  struct utmp u;
  2087. X
  2088. X  strncpy(u.ut_line, name, 8);
  2089. X  strncpy(u.ut_name, LoginName, 8);
  2090. X  u.ut_type = 7; /* USER_PROCESS */
  2091. X  strncpy(u.ut_id, name+3, 4);
  2092. X  (void) time(&u.ut_time);
  2093. X  slot = (lseek(utmpfappend, 0, 2) + 1) / sizeof u;
  2094. X  (void) write(utmpfappend, (char *)&u, sizeof u);
  2095. X  close(utmpfappend);
  2096. X  if ((utmpfappend = open(UtmpName, O_APPEND)) == -1) 
  2097. X    {
  2098. X      if (errno != EACCES)
  2099. X        Msg(errno, UtmpName);
  2100. X      return;
  2101. X    }
  2102. X  return slot;
  2103. X}
  2104. X#endif /* MIPS */
  2105. X
  2106. X/*
  2107. X * if slot could be removed or was 0,  wi->slot = -1;
  2108. X * else not changed.
  2109. X */
  2110. int
  2111. RemoveUtmp(wi)
  2112. struct win *wi;
  2113. X{
  2114. X#ifdef GETUTENT
  2115. X  struct utmp *uu;
  2116. X#endif
  2117. X  struct utmp u;
  2118. X  slot_t slot;
  2119. X
  2120. X  slot=wi->slot;
  2121. X#ifdef GETUTENT
  2122. X  debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
  2123. X         "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
  2124. X#else
  2125. X  debug1("RemoveUtmp(wi.slot: %d)\n", slot);
  2126. X#endif
  2127. X  if (!utmp)
  2128. X    return -1;
  2129. X  if (slot == (slot_t) 0 || slot == (slot_t) -1)
  2130. X    {
  2131. X      debug1("There is no utmp-slot to be removed(%d)\n", slot);
  2132. X      wi->slot = (slot_t) -1;
  2133. X      return 0;
  2134. X    }
  2135. X  bzero((char *) &u, sizeof u);
  2136. X#ifdef GETUTENT
  2137. X  setutent();
  2138. X  strncpy(u.ut_line, slot, sizeof(u.ut_line));
  2139. X  if ((uu = getutline(&u)) == 0)
  2140. X    {
  2141. X      Msg(0, "Utmp slot not found -> not removed");
  2142. X      return -1;
  2143. X    }
  2144. X# ifdef _SEQUENT_
  2145. X  if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  2146. X# else
  2147. X  uu->ut_type = DEAD_PROCESS;
  2148. X  uu->ut_exit.e_termination = 0;
  2149. X  uu->ut_exit.e_exit= 0;
  2150. X  if (pututline(uu) == 0)
  2151. X# endif
  2152. X#else    /* GETUTENT */
  2153. X  (void) lseek(utmpf, (off_t) (slot * sizeof u), 0);
  2154. X  if (write(utmpf, (char *) &u, sizeof u) != sizeof u)
  2155. X#endif
  2156. X    {
  2157. X#ifdef NETHACK
  2158. X      if (nethackflag)
  2159. X        Msg(errno, "/etc/utmp is to hard to dig");
  2160. X      else
  2161. X#endif
  2162. X      Msg(errno,"Could not write /etc/utmp");
  2163. X      return -1;
  2164. X    }
  2165. X  debug("RemoveUtmp successful\n");
  2166. X  wi->slot = (slot_t) -1;
  2167. X  return 0;
  2168. X}
  2169. X
  2170. X#endif    /* UTMPOK */
  2171. X
  2172. X#if !defined(GETTTYENT) && !defined(GETUTENT)
  2173. X
  2174. static void setttyent()
  2175. X{
  2176. X  struct stat s;
  2177. X  register int f;
  2178. X  register char *p, *ep;
  2179. X
  2180. X  if (ttnext)
  2181. X    {
  2182. X      ttnext = tt;
  2183. X      return;
  2184. X    }
  2185. X  if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
  2186. X    Msg(errno, ttys);
  2187. X  if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
  2188. X    Msg_nomem;
  2189. X  if (read(f, tt, s.st_size) != s.st_size)
  2190. X    Msg(errno, ttys);
  2191. X  close(f);
  2192. X  for (p = tt, ep = p + s.st_size; p < ep; ++p)
  2193. X    if (*p == '\n')
  2194. X      *p = '\0';
  2195. X  *p = '\0';
  2196. X  ttnext = tt;
  2197. X}
  2198. X
  2199. static struct ttyent *getttyent()
  2200. X{
  2201. X  static struct ttyent t;
  2202. X
  2203. X  if (*ttnext == '\0')
  2204. X    return NULL;
  2205. X  t.ty_name = ttnext + 2;
  2206. X  ttnext += strlen(ttnext) + 1;
  2207. X  return &t;
  2208. X}
  2209. X
  2210. X#endif    /* GETTTYENT */
  2211. X
  2212. X#ifdef LOADAV
  2213. X
  2214. void
  2215. InitKmem()
  2216. X{
  2217. X  debug("Init Kmem...\n");
  2218. X  if ((kmemf = open(KmemName, O_RDONLY)) == -1)
  2219. X    return;
  2220. X  debug("Kmem opened\n");
  2221. X  nl[0].n_name = AvenrunSym;
  2222. X  debug2("Searching in %s for %s\n", UnixName, nl[0].n_name);
  2223. X  nlist(UnixName, nl);
  2224. X  if (/* nl[0].n_type == 0 || */ nl[0].n_value == 0)
  2225. X    {
  2226. X      close(kmemf);
  2227. X      return;
  2228. X    }
  2229. X  debug("AvenrunSym found!!\n");
  2230. X  avenrun = 1;
  2231. X}
  2232. X
  2233. int
  2234. GetAvenrun()
  2235. X{
  2236. X  if (lseek(kmemf, (off_t) nl[0].n_value, 0) == (off_t) - 1)
  2237. X    return 0;
  2238. X  if (read(kmemf, (char *) loadav, sizeof loadav) != sizeof loadav)
  2239. X    return 0;
  2240. X
  2241. X  return 1;
  2242. X}
  2243. X
  2244. X#endif    /* LOADAV */
  2245. X
  2246. X
  2247. X/*
  2248. X * (Almost) secure open and fopen... mlschroe.
  2249. X */
  2250. X
  2251. XFILE *
  2252. secfopen(name, mode)
  2253. char *name;
  2254. char *mode;
  2255. X{
  2256. X  FILE *fi;
  2257. X#ifdef NOREUID
  2258. X  int flags, fd;
  2259. X#endif
  2260. X
  2261. X  debug2("secfopen(%s, %s)\n", name, mode);
  2262. X  if (eff_uid == real_uid)
  2263. X    return(fopen(name, mode));
  2264. X#ifndef NOREUID
  2265. X  setreuid(eff_uid, real_uid);
  2266. X  setregid(eff_gid, real_gid);
  2267. X  fi = fopen(name, mode);
  2268. X  setreuid(real_uid, eff_uid);
  2269. X  setregid(real_gid, eff_gid);
  2270. X#else
  2271. X  if (mode[0] && mode[1] == '+')
  2272. X    flags = O_RDWR;
  2273. X  else
  2274. X    flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
  2275. X  if (mode[0] == 'w')
  2276. X    flags |= O_CREAT | O_TRUNC;
  2277. X  else if (mode[0] == 'a')
  2278. X    flags |= O_CREAT | O_APPEND;
  2279. X  else if (mode[0] != 'r')
  2280. X    {
  2281. X      errno = EINVAL;
  2282. X      return(0);
  2283. X    }
  2284. X  if ((fd = secopen(name, flags, 0666)) < 0)
  2285. X    return(0);
  2286. X  if ((fi = fdopen(fd, mode)) == 0)
  2287. X    {
  2288. X      close(fd);
  2289. X      return(0);
  2290. X    }
  2291. X#endif
  2292. X  return(fi);
  2293. X}
  2294. X
  2295. X
  2296. int
  2297. secopen(name, flags, mode)
  2298. char *name;
  2299. int flags;
  2300. int mode;
  2301. X{
  2302. X  int fd;
  2303. X#ifdef NOREUID
  2304. X  int q;
  2305. X  struct stat stb;
  2306. X#endif
  2307. X
  2308. X  debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
  2309. X  if (eff_uid == real_uid)
  2310. X    return(open(name, flags, mode));
  2311. X#ifndef NOREUID
  2312. X  setreuid(eff_uid, real_uid);
  2313. X  setregid(eff_gid, real_gid);
  2314. X  fd = open(name, flags, mode);
  2315. X  setreuid(real_uid, eff_uid);
  2316. X  setregid(real_gid, eff_gid);
  2317. X#else
  2318. X  /* Truncation/creation is done in UserContext */
  2319. X  if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK)))
  2320. X    {
  2321. X      if (UserContext() > 0)
  2322. X    {
  2323. X          if ((fd = open(name, flags, mode)) >= 0)
  2324. X        {
  2325. X          close(fd);
  2326. X          UserReturn(0);
  2327. X            }
  2328. X      if (errno == 0)
  2329. X        errno = EACCES;
  2330. X      UserReturn(errno);
  2331. X    }
  2332. X      if (q = UserStatus())
  2333. X    {
  2334. X      if (q > 0)
  2335. X        errno = q;
  2336. X          return(-1);
  2337. X    }
  2338. X    }
  2339. X  if (access(name, F_OK))
  2340. X    return(-1);
  2341. X  if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
  2342. X    return(-1);
  2343. X  debug("open successful\n");
  2344. X  if (fstat(fd, &stb))
  2345. X    {
  2346. X      close(fd);
  2347. X      return(-1);
  2348. X    }
  2349. X  debug("fstat successful\n");
  2350. X  if (stb.st_uid != real_uid)
  2351. X    {
  2352. X      switch (flags & (O_RDONLY | O_WRONLY | O_RDWR))
  2353. X        {
  2354. X    case O_RDONLY:
  2355. X      q = 0004;
  2356. X      break;
  2357. X    case O_WRONLY:
  2358. X      q = 0002;
  2359. X      break;
  2360. X    default:
  2361. X      q = 0006;
  2362. X      break;
  2363. X        }
  2364. X      if ((stb.st_mode & q) != q)
  2365. X    {
  2366. X          debug("secopen: permission denied\n");
  2367. X      close(fd);
  2368. X      errno = EACCES;
  2369. X      return(-1);
  2370. X    }
  2371. X    }
  2372. X#endif
  2373. X  debug1("secopen ok - returning %d\n", fd);
  2374. X  return(fd);
  2375. X}
  2376. END_OF_FILE
  2377. if test 49381 -ne `wc -c <'fileio.c'`; then
  2378.     echo shar: \"'fileio.c'\" unpacked with wrong size!
  2379. fi
  2380. # end of 'fileio.c'
  2381. fi
  2382. echo shar: End of archive 5 \(of 8\).
  2383. cp /dev/null ark5isdone
  2384. MISSING=""
  2385. for I in 1 2 3 4 5 6 7 8 ; do
  2386.     if test ! -f ark${I}isdone ; then
  2387.     MISSING="${MISSING} ${I}"
  2388.     fi
  2389. done
  2390. if test "${MISSING}" = "" ; then
  2391.     echo You have unpacked all 8 archives.
  2392.     rm -f ark[1-9]isdone
  2393. else
  2394.     echo You still need to unpack the following archives:
  2395.     echo "        " ${MISSING}
  2396. fi
  2397. ##  End of shell archive.
  2398. exit 0
  2399.